home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1999 March
/
EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso
/
earcd
/
devel
/
vbcc-wos-src
/
pasm
/
directives.c
next >
Wrap
C/C++ Source or Header
|
1999-01-01
|
27KB
|
1,133 lines
/* $VER: pasm directives.c V1.1d (27.09.98)
*
* This file is part of pasm, a portable PowerPC assembler.
* Copyright (c) 1997-98 Frank Wille
*
* pasm is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
* pasm may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v1.1d (27.09.98) phx
* Allow blanks after string constants.
* v1.1c (22.09.98) phx
* Include file name was trashed (allocstring() was missing).
* v1.1b (05.07.98) phx
* Introduced section flags SF_CHIP and SF_FAST for EHF/ADos. They
* are set by the new section attributes "C" and "F".
* v1.1 (19.06.98) phx
* New directive .sdreg which sets the small data base
* register (default r2).
* .SDREG replaces the obsolete .BASEREL directive!
* v1.0 (04.04.98) phx
* Hack in _uahalf() to make ADDR16-relocation work for instructions.
* v0.8 (14.02.98) phx
* Alignment list for each section. This fixes the problems
* with optimizations.
* v0.6 (30.10.97) phx
* The names of macros will be converted to lower case (otherwise,
* they would remain inaccessible ;)
* v0.5 (12.10.97) phx
* .set directive is allowed multiple times on the same symbol.
* If a .set-assignment can't be resolved in pass 1, the symbol
* is no longer undefined, but defined with an absolute default
* value of '1'. So .ifdef will work correctly.
* .globl directive declares unknown symbols in pass 1 as
* externally defined. If the symbol is defined later in the
* source, it will be made global by add_symbol()/tables.c.
* v0.4 (29.04.97) phx
* .new_section sets type of section-symbol to SYMI_SECTION.
* New directives: .baserel
* v0.3 (10.04.97) phx
* Some vbcc-specific changes.
* v0.2 (25.03.97) phx
* Writes ELF object for 32-bit PowerPC big-endian. Either absolute
* or ELF output format may be selected. ELF is default for all
* currently supported platforms. PPCasm supports nine different
* relocation types (there are much more...).
* Compiles and works also under NetBSD/amiga (68k).
* Changed function declaration to 'new style' in all sources
* (to avoid problems with '...' for example).
* Floating pointer support. New directives: .fail, .ident, .file,
* .float, .ufloat, .double, .udouble, .local.
* v0.1 (11.03.97) phx
* First test version with all PowerPC instructions and most
* important directives. Only raw, absolute output.
* .ident and .file directives are supported, but have no effect.
* Especially floating point directives are missing.
* v0.0 (21.02.97) phx
* File created.
*/
#define DIRECTIVES_C
#include "ppcasm.h"
void activate_section(struct GlobalVars *,struct Section *);
void alignment(struct GlobalVars *,unsigned long);
char escchar(char);
static void start_section(struct GlobalVars *,struct ParsedLine *pl,bool);
static char *section_attributes(struct GlobalVars *,char *,uint8 *,
uint8 *,uint8 *,uint8 *);
static void _uahalf(struct GlobalVars *,struct ParsedLine *);
static void _uaword(struct GlobalVars *,struct ParsedLine *);
static void uafloat(struct GlobalVars *,struct ParsedLine *,bool);
static void ifeqs(struct GlobalVars *,struct ParsedLine *,int);
static void ifdef(struct GlobalVars *,struct ParsedLine *,bool);
static void _new_section(struct GlobalVars *gv,struct ParsedLine *pl)
{
start_section(gv,pl,1);
}
static void _section(struct GlobalVars *gv,struct ParsedLine *pl)
{
start_section(gv,pl,0);
}
static void start_section(struct GlobalVars *gv,struct ParsedLine *pl,
bool force_new)
/* define a new section with new attributes or reactivate a */
/* previously defined one */
{
struct Section *nexts,*sec = (struct Section *)gv->sectionlist.first;
struct Symbol *sym;
struct AlignPoint *ap;
char *s,*name;
uint8 type,flags,protection,alignment;
s = getarg(gv,pl->operand); /* section's name */
name = remquotes(gv->strbuf);
while (nexts = (struct Section *)sec->n.next) {
if (!strcmp(name,sec->name)) {
if (force_new) { /* overwrite an old section with the same name? */
sprintf(gv->strbuf,"%s_%08lx",sec->name,(unsigned long)sec);
name = sec->name;
sec->name = allocstring(gv->strbuf);
break;
}
else { /* reactivate old section with the same name */
s = section_attributes(gv,s,&type,&flags,&protection,&alignment);
if (type != ST_UNDEFINED) /* attributes specified? */
if (sec->type!=type || sec->flags!=flags ||
sec->protection!=protection || sec->alignment!=alignment)
error(16); /* section attributes don't match */
pl->type = OT_SECTION;
pl->opcode = (void *)sec;
activate_section(gv,sec);
checkEOL(s);
return;
}
}
sec = nexts;
}
/* create a new section */
sec = alloczero(sizeof(struct Section));
sec->name = allocstring(name);
s = section_attributes(gv,s,&sec->type,&sec->flags,&sec->protection,
&sec->alignment);
if (sec->type == ST_UNDEFINED) { /* set default attributes */
sec->type = ST_DATA;
sec->protection = SP_READ|SP_WRITE;
sec->alignment = 2;
}
initlist(&sec->reloclist);
initlist(&sec->xreflist);
ap = alloc(sizeof(struct AlignPoint));
ap->next = NULL;
ap->offset = ap->gap = 0;
ap->val = 1 << sec->alignment;
sec->first_align = sec->current_align = ap;
addtail(&gv->sectionlist,&sec->n);
pl->type = OT_SECTION;
pl->opcode = (void *)sec;
activate_section(gv,sec);
sym = add_symbol(gv,sec->name,SYM_RELOC,0);
sym->info = SYMI_SECTION;
checkEOL(s);
}
void activate_section(struct GlobalVars *gv,struct Section *sec)
{
gv->csect = sec; /* set active section */
gv->lcsym->relsect = sec;
gv->lcsym->value = sec->pc;
}
static char *section_attributes(struct GlobalVars *gv,char *s,uint8 *t,
uint8 *f,uint8 *p,uint8 *a)
/* fill in section attributes, if specified */
{
char c,*attr;
*t = ST_UNDEFINED;
*f = *p = *a = 0;
s = skipspaces(s);
if (*s) {
if (*s == ',') {
s = skipspaces(++s);
s = getarg(gv,s);
c = *gv->strbuf;
if (c=='\"' || c=='\'') {
attr = remquotes(gv->strbuf);
while (c = *attr++) {
switch (c) {
/* contents type */
case 'c':
*t = ST_CODE;
break;
case 'd':
*t = ST_DATA;
break;
case 'u':
*t = ST_UDATA;
*f |= SF_UNINITIALIZED;
break;
case 'i':
*t = ST_STRUCT;
*f |= SF_DISCARD|SF_UNINITIALIZED;
break;
/* protection */
case 'r':
*p |= SP_READ;
break;
case 'w':
*p |= SP_WRITE;
break;
case 'x':
*p |= SP_EXEC;
break;
case 's':
*p |= SP_SHARE;
break;
case 'n': /* remove and discard currently not supported */
case 'R':
break;
case 'C':
*f |= SF_CHIP;
break;
case 'F':
*f |= SF_FAST;
break;
default:
if (c>='0' && c <='6')
*a = (uint8)(c-'0'); /* alignment */
else
error(15,c); /* illegal section attribute */
break;
}
}
}
else
error(14); /* string constant expected */
}
else if (*s != '#')
error(12); /* colon expected */
}
return (s);
}
static void _set(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s = getsymbol(gv,pl->operand);
struct Expression exp;
struct Section *cs;
char setname[STRBUFSIZE];
struct Symbol *sym;
if (*gv->strbuf) {
strcpy(setname,gv->strbuf);
if (s = check_comma(s)) {
s = eval_expression(gv,&exp,s);
if (exp.type != SYM_UNDEF) {
if (exp.type != SYM_EXTERN) {
if (exp.type == SYM_RELOC) {
if (exp.reloctype == R_PPC_ADDR32) {
if (sym = search_symbol(gv,setname)) {
sym->value = exp.value;
sym->type = SYM_RELOC;
sym->relsect = exp.symbol->relsect;
}
else {
cs = gv->csect;
gv->csect = exp.symbol->relsect;
add_symbol(gv,setname,SYM_RELOC,exp.value);
gv->csect = cs;
}
}
else
error(29); /* can't assign relocatable half word */
}
else {
if (sym = search_symbol(gv,setname)) {
sym->value = exp.value;
sym->type = SYM_ABS;
}
else
add_symbol(gv,setname,SYM_ABS,exp.value);
}
}
else
error(28); /* can't assign external symbol */
}
else {
if (gv->pass) /* expression still undefined in pass 2 ? */
error(19); /* undefined symbol */
else if (!search_symbol(gv,setname))
/* set value to 1 if unknown in first pass */
add_symbol(gv,setname,SYM_ABS,1);
}
checkEOL(s);
return;
}
}
else
error(17); /* missing argument */
}
static void _macro(struct GlobalVars *gv,struct ParsedLine *pl)
{
struct Macro *mac = alloczero(sizeof(struct Macro));
char *s = getsymbol(gv,pl->operand);
mac->name = allocstring(gv->strbuf);
lower_case(mac->name); /* convert macro name to lower case */
mac->text = gv->cthread->srcptr;
mac->nlines = gv->absline + 1;
gv->cthread->macskip = mac;
pl->type = OT_IGNORE; /* ignore in pass 2 */
checkEOL(s);
}
static void _include(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s;
if (!gv->pass) { /* pass 1 */
s = getarg(gv,pl->operand); /* include file's name */
/* recursively call pass 1 and create new SourceThread */
pass1(gv,include_source(gv,allocstring(remquotes(gv->strbuf))),
NULL,gv->cthread);
checkEOL(s);
}
else /* recursively call pass 2 */
pass2(gv,get_source(gv),NULL,gv->cthread);
}
void alignment(struct GlobalVars *gv,unsigned long a)
{
unsigned long x = (1<<a) - 1;
unsigned long pc, oldpc = gv->csect->pc;
struct AlignPoint *ap = gv->csect->current_align;
pc = (oldpc + x) & ~x;
if (!gv->pass) {
if (ap->next)
ierror("Current alignment point is not the last one!");
ap->next = alloc(sizeof(struct AlignPoint));
ap = ap->next;
ap->next = NULL;
ap->offset = oldpc;
ap->val = 1 << a;
ap->gap = pc - oldpc;
gv->csect->current_align = ap;
gv->csect->pc = pc;
}
else {
if (!(gv->csect->current_align = ap->next)) /* next alignment section */
ierror("No more alignments in list!");
store_space(gv,pc-oldpc);
}
}
static void _align(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s;
uint32 a=2;
static uint8 na=0;
if (pl->flags & PLF_ALIGN) {
if (++na > 2)
gv->vc = TRUE;
}
else
na = 0;
s = getintexp(gv,pl->operand,&a);
alignment(gv,a);
gv->alignflag = TRUE;
if (!gv->pass)
checkEOL(s);
}
static void _space(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s;
uint32 n=0;
s = getintexp(gv,pl->operand,&n);
if (!gv->pass) {
pcadd(gv,n);
checkEOL(s);
}
else
store_space(gv,n);
}
char escchar(char c)
/* convert escape code */
{
switch (c) {
case 'b':
c = 8;
break;
case 'f':
c = 12;
break;
case 'n':
c = 10;
break;
case 'r':
c = 13;
break;
case 't':
c = 8;
break;
}
return (c);
}
static void _byte(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s = pl->operand;
char *sb,c;
uint8 pass = gv->pass;
uint32 i;
for (;;) {
if ((c = *s) == '\"') { /* read string */
s = getarg(gv,s);
sb = remquotes(gv->strbuf);
if (!pass)
while (c = *sb++) {
if (c=='\\' || c=='\"')
if (*sb++ == 0)
break;
pcadd(gv,1);
}
else
while (c = *sb++) {
if (c == '\\') {
if (!(c = escchar(*sb++)))
break;
}
else if (c == '\"') {
if (!(c = *sb++))
break;
}
store_byte(gv,(uint8)c);
}
s = skipspaces(s);
}
else { /* get integer expression */
if (c==0 || c=='#') {
error(17); /* missing argument */
break;
}
if (!pass) {
s = skipexpression(gv,s);
pcadd(gv,1);
}
else {
s = getintexp(gv,s,&i);
store_byte(gv,(uint8)i);
s = skipspaces(s);
}
}
c = *s++;
if (c==0 || c=='#') /* no more arguments? */
break;
if (c != ',') {
error(12); /* colon expected */
break;
}
s = skipspaces(s);
}
}
static void _string(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s = pl->operand;
char *sb,c;
uint8 pass = gv->pass;
for (;;) {
if ((c = *s) == '\"') { /* read string */
s = getarg(gv,s);
sb = remquotes(gv->strbuf);
if (!pass) {
while (c = *sb++) {
if (c=='\\' || c=='\"')
if (*sb++ == 0)
break;
pcadd(gv,1);
}
pcadd(gv,1);
}
else {
while (c = *sb++) {
if (c == '\\') {
if (!(c = escchar(*sb++)))
break;
}
else if (c == '\"') {
if (!(c = *sb++))
break;
}
store_byte(gv,(uint8)c);
}
store_byte(gv,0);
}
s = skipspaces(s);
}
else {
error(14); /* string constant expected */
break;
}
c = *s++;
if (c==0 || c=='#') /* no more arguments? */
break;
if (c != ',') {
error(12); /* colon expected */
break;
}
s = skipspaces(s);
}
}
static void _half(struct GlobalVars *gv,struct ParsedLine *pl)
{
alignment(gv,1);
_uahalf(gv,pl);
}
static void _uahalf(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s = pl->operand;
char *sb,c;
uint8 pass = gv->pass;
uint32 i;
for (;;) {
c = *s;
if (c==0 || c=='#') {
error(17); /* missing argument */
break;
}
if (!pass) {
s = skipexpression(gv,s);
pcadd(gv,2);
}
else {
gv->csect->pc -= 2;
s = getexp(gv,s,&i,2);
gv->csect->pc += 2;
store_half(gv,(uint16)i);
s = skipspaces(s);
}
c = *s++;
if (c==0 || c=='#') /* no more arguments? */
break;
if (c != ',') {
error(12); /* colon expected */
break;
}
s = skipspaces(s);
}
}
static void _word(struct GlobalVars *gv,struct ParsedLine *pl)
{
alignment(gv,2);
_uaword(gv,pl);
}
static void _uaword(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s = pl->operand;
char *sb,c;
uint8 pass = gv->pass;
uint32 i;
for (;;) {
c = *s;
if (c==0 || c=='#') {
error(17); /* missing argument */
break;
}
if (!pass) {
s = skipexpression(gv,s);
pcadd(gv,4);
}
else {
s = getexp(gv,s,&i,4);
store_word(gv,i);
s = skipspaces(s);
}
c = *s++;
if (c==0 || c=='#') /* no more arguments? */
break;
if (c != ',') {
error(12); /* colon expected */
break;
}
s = skipspaces(s);
}
}
static void _float(struct GlobalVars *gv,struct ParsedLine *pl)
{
alignment(gv,2);
uafloat(gv,pl,FALSE);
}
static void _uafloat(struct GlobalVars *gv,struct ParsedLine *pl)
{
uafloat(gv,pl,FALSE);
}
static void _double(struct GlobalVars *gv,struct ParsedLine *pl)
{
alignment(gv,3);
uafloat(gv,pl,TRUE);
}
static void _uadouble(struct GlobalVars *gv,struct ParsedLine *pl)
{
uafloat(gv,pl,TRUE);
}
static void uafloat(struct GlobalVars *gv,struct ParsedLine *pl,bool dbl)
{
char *s = pl->operand;
char *sb,c;
uint8 pass = gv->pass;
double f;
for (;;) {
c = *s;
if (c==0 || c=='#') {
error(17); /* missing argument */
break;
}
if (!pass) {
s = skipexpression(gv,s);
pcadd(gv,dbl?8:4);
}
else {
sscanf(s,"%lf",&f);
if (dbl)
store_double(gv,f);
else
store_float(gv,f);
s = skipexpression(gv,s);
}
c = *s++;
if (c==0 || c=='#') /* no more arguments? */
break;
if (c != ',') {
error(12); /* colon expected */
break;
}
s = skipspaces(s);
}
}
static void _globl(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s;
struct Symbol *sym;
s = getsymbol(gv,pl->operand);
if (*gv->strbuf) {
if (!(sym = search_symbol(gv,gv->strbuf))) {
/* unknown in pass 1, then declare as externally defined first */
sym = add_symbol(gv,gv->strbuf,SYM_EXTERN,0);
}
sym->bind = SYMB_GLOBAL;
checkEOL(s);
}
else
error(17); /* missing argument */
pl->type = OT_IGNORE; /* ignore in pass 2 */
}
static void _local(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s;
struct Symbol *sym;
if (gv->pass) {
s = getsymbol(gv,pl->operand);
if (*gv->strbuf) {
if (!(sym = search_symbol(gv,gv->strbuf)))
error(19); /* undefined symbol */
else
sym->bind = SYMB_LOCAL;
checkEOL(s);
}
else
error(17); /* missing argument */
}
}
static void _bss(struct GlobalVars *gv,struct ParsedLine *pl)
{
static char *bssname=".bss";
char *s;
struct Section *bss,*old=gv->csect;
uint32 size,align;
char symbname[STRBUFSIZE];
struct Symbol *sym;
s = getsymbol(gv,pl->operand);
if (*gv->strbuf) {
if (!gv->pass)
strcpy(symbname,gv->strbuf);
if (!(s = check_comma(s)))
return;
s = getintexp(gv,s,&size); /* size of bss symbol */
align = (size>=8)? 3 : 2;
s = skipspaces(s);
if (*s == ',') {
s = getintexp(gv,++s,&align); /* optional aligment */
if (align < 2)
align = 2;
}
if (bss = search_section(gv,bssname)) {
activate_section(gv,bss);
alignment(gv,align);
if (!gv->pass) {
sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
sym->info = SYMI_OBJECT;
sym->size = size;
sym->bind = SYMB_LOCAL;
pcadd(gv,size);
checkEOL(s);
}
else
store_space(gv,size);
activate_section(gv,old);
}
else
error(47,bssname); /* section .bss was never defined */
}
else
error(17); /* missing argument */
}
static void _comm(struct GlobalVars *gv,struct ParsedLine *pl)
{
static char *bssname=".bss";
char *s;
struct Section *bss,*old=gv->csect;
uint32 size;
char symbname[STRBUFSIZE];
struct Symbol *sym;
s = getsymbol(gv,pl->operand);
if (*gv->strbuf) {
if (!gv->pass)
strcpy(symbname,gv->strbuf);
if (!(s = check_comma(s)))
return;
s = getintexp(gv,s,&size); /* size of bss symbol */
if (bss = search_section(gv,bssname)) {
activate_section(gv,bss);
alignment(gv,(size>=8)? 3:2);
if (!gv->pass) {
sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
sym->info = SYMI_OBJECT;
sym->size = size;
sym->bind = SYMB_GLOBAL; /* or SYMB_WEAK ?? */
pcadd(gv,size);
checkEOL(s);
}
else
store_space(gv,size);
activate_section(gv,old);
}
else
error(47,bssname); /* section .bss was never defined */
}
else
error(17); /* missing argument */
}
static void _type(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s;
struct Symbol *sym;
uint32 type;
if (gv->pass) {
s = getsymbol(gv,pl->operand);
if (*gv->strbuf) {
if (sym = search_symbol(gv,gv->strbuf)) {
if (s = check_comma(s)) {
s = getintexp(gv,s,&type);
sym->info = (uint8)type;
checkEOL(s);
}
}
else
error(19); /* undefined symbol */
}
else
error(17); /* missing argument */
}
}
static void _size(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s;
struct Symbol *sym;
uint32 size;
if (gv->pass) {
s = getsymbol(gv,pl->operand);
if (*gv->strbuf) {
if (sym = search_symbol(gv,gv->strbuf)) {
if (s = check_comma(s)) {
s = getintexp(gv,s,&size);
sym->size = size;
checkEOL(s);
}
}
else
error(19); /* undefined symbol */
}
else
error(17); /* missing argument */
}
}
static void _ifeq(struct GlobalVars *gv,struct ParsedLine *pl)
{
ifeqs(gv,pl,0);
}
static void _ifne(struct GlobalVars *gv,struct ParsedLine *pl)
{
ifeqs(gv,pl,1);
}
static void _ifgt(struct GlobalVars *gv,struct ParsedLine *pl)
{
ifeqs(gv,pl,2);
}
static void _ifge(struct GlobalVars *gv,struct ParsedLine *pl)
{
ifeqs(gv,pl,3);
}
static void _iflt(struct GlobalVars *gv,struct ParsedLine *pl)
{
ifeqs(gv,pl,4);
}
static void _ifle(struct GlobalVars *gv,struct ParsedLine *pl)
{
ifeqs(gv,pl,5);
}
static void ifeqs(struct GlobalVars *gv,struct ParsedLine *pl,int cond)
{
char *s;
int32 val;
bool *condptr;
if (gv->iflevel < (MAX_IFLEVELS-1)) {
condptr = &gv->ifcond[++gv->iflevel];
*condptr = FALSE;
s = getintexp(gv,pl->operand,&val);
switch (cond) {
case 0: /* eq */
if (val==0)
*condptr = TRUE;
break;
case 1: /* ne */
if (val!=0)
*condptr = TRUE;
break;
case 2: /* gt */
if (val>0)
*condptr = TRUE;
break;
case 3: /* ge */
if (val>=0)
*condptr = TRUE;
break;
case 4: /* lt */
if (val<0)
*condptr = TRUE;
break;
case 5: /* le */
if (val<=0)
*condptr = TRUE;
break;
}
checkEOL(s);
}
else
error(43); /* maximum nesting depth for conditional assembly exceeded */
pl->type = OT_IGNORE; /* ignore in pass 2 */
}
static void _ifdef(struct GlobalVars *gv,struct ParsedLine *pl)
{
ifdef(gv,pl,TRUE);
}
static void _ifndef(struct GlobalVars *gv,struct ParsedLine *pl)
{
ifdef(gv,pl,FALSE);
}
static void ifdef(struct GlobalVars *gv,struct ParsedLine *pl,bool c)
{
char *s;
bool *condptr;
if (gv->iflevel < (MAX_IFLEVELS-1)) {
condptr = &gv->ifcond[++gv->iflevel];
*condptr = c ? FALSE:TRUE;
s = getsymbol(gv,pl->operand);
if (*gv->strbuf)
if (search_symbol(gv,gv->strbuf))
*condptr = c;
checkEOL(s);
}
else
error(43); /* maximum nesting depth for conditional assembly exceeded */
pl->type = OT_IGNORE; /* ignore in pass 2 */
}
static void _else(struct GlobalVars *gv,struct ParsedLine *pl)
{
if (gv->iflevel > 0) {
gv->ifcond[gv->iflevel] = FALSE;
checkEOL(pl->operand);
}
else
error(44,".else"); /* .else without matching .if */
pl->type = OT_IGNORE; /* ignore in pass 2 */
}
static void _endif(struct GlobalVars *gv,struct ParsedLine *pl)
{
if (gv->iflevel > 0) {
gv->iflevel--;
checkEOL(pl->operand);
}
else
error(44,".endif"); /* .endif without matching .if */
pl->type = OT_IGNORE; /* ignore in pass 2 */
}
static void _fail(struct GlobalVars *gv,struct ParsedLine *pl)
{
error(45); /* fail directive encountered */
}
static void _noop(struct GlobalVars *gv,struct ParsedLine *pl)
{
}
static void _ident(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s = getarg(gv,pl->operand); /* identification / comment */
gv->ident = allocstring(remquotes(gv->strbuf));
checkEOL(s);
pl->type = OT_IGNORE; /* ignore in pass 2 */
}
static void _file(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s = getarg(gv,pl->operand); /* source file name */
gv->file = allocstring(remquotes(gv->strbuf));
checkEOL(s);
pl->type = OT_IGNORE; /* ignore in pass 2 */
}
static void _baserel(struct GlobalVars *gv,struct ParsedLine *pl)
/* OBSOLETE SINCE V1.1. */
/* The .baserel directive only exists for compatibilty with older sources */
{
char *s;
struct Symbol *sym;
uint32 tocreg;
if (gv->pass) {
s = getsymbol(gv,pl->operand);
if (*gv->strbuf) {
if (sym = search_symbol(gv,gv->strbuf)) {
if (s = check_comma(s)) {
s = getintexp(gv,s,&tocreg);
if (sym->info == SYMI_SECTION) {
/* activate new base relative addressing mode */
gv->tocsect = sym->relsect;
gv->rtoc = (int)tocreg;
}
else
error(50,sym->name); /* symbol is not a section base address */
checkEOL(s);
}
}
else
error(19); /* undefined symbol */
}
else
error(17); /* missing argument */
}
}
static void _sdreg(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s;
uint32 tocreg;
if (gv->pass) {
s = getintexp(gv,pl->operand,&tocreg);
if (tocreg < 32) {
gv->rtoc = (int)tocreg;
gv->tocsect = NULL; /* disable single sd-section mode */
}
else
error(31); /* wrong register */
checkEOL(s);
}
}
struct Directive directives[] = {
0,".new_section",_new_section,
0,".section",_section,
0,".set",_set,
0,".macro",_macro,
0,".include",_include,
0,".align",_align,
0,".space",_space,
0,".byte",_byte,
0,".ascii",_byte,
0,".string",_string,
0,".asciiz",_string,
0,".half",_half,
0,".short",_half,
0,".word",_word,
0,".long",_word,
0,".float",_float,
0,".double",_double,
0,".uahalf",_uahalf,
0,".uashort",_uahalf,
0,".uaword",_uaword,
0,".ualong",_uaword,
0,".uafloat",_uafloat,
0,".uadouble",_uadouble,
0,".globl",_globl,
0,".global",_globl,
0,".extern",_globl,
0,".local",_local,
0,".bss",_bss,
0,".lcomm",_bss,
0,".comm",_comm,
0,".type",_type,
0,".size",_size,
0,".if",_ifne,
0,".ifeq",_ifeq,
0,".ifne",_ifne,
0,".ifgt",_ifgt,
0,".ifge",_ifge,
0,".iflt",_iflt,
0,".ifle",_ifle,
0,".ifdef",_ifdef,
0,".ifndef",_ifndef,
0,".else",_else,
0,".endif",_endif,
0,".fail",_fail,
0,".ident",_ident,
0,".file",_file,
0,".baserel",_baserel,
0,".sdreg",_sdreg,
0,0 /* end mark */
};